/*************  技术支持与购买说明    **************
产品主页：http://tw51.haohaodada.com
淘宝搜索：天问51，可购买。目前基础版99元，带彩屏标准备版149元，旗舰版299
技术支持QQ群一：1138055784
******************************************/

#ifndef _CAN_H_
#define _CAN_H_

//此枚举定义不允许用户修改
typedef enum //枚举串口引脚
{
	CAN_RX_P00, CAN_TX_P01,		//只能使用同一行的RX和TX引脚号。不允许混用
    CAN_RX_P50, CAN_TX_P51,
    CAN_RX_P42, CAN_TX_P45,
    CAN_RX_P70, CAN_TX_P71
}CAN_PIN;

void CANInit(CAN_PIN rx_pin, CAN_PIN tx_pin);
void CanSendMsg(uint16 canid, uint8 *pdat, uint8 len);
uint16 CanReadMsg(uint8 *pdat);

//========================================================================
// 描述: CAN功能寄存器读取函数。
// 参数: CAN功能寄存器地址.
// 返回: CAN功能寄存器数据.
//========================================================================
uint8 CanReadReg(uint8 addr)
{
	uint8 dat;
	CANAR = addr;
	dat = CANDR;
	return dat;
}

//========================================================================
// 描述: CAN功能寄存器配置函数。
// 参数: CAN功能寄存器地址, CAN功能寄存器数据.
// 返回: none.
//========================================================================
void CanWriteReg(uint8 addr, uint8 dat)
{
	CANAR = addr;
	CANDR = dat;
}

//========================================================================
// 描述: 读取CAN缓冲区数据函数。
// 参数: *pdat: 存放CAN缓冲区数据.
// 返回: none.
//========================================================================
void CanReadFifo(uint8 *pdat)
{
	pdat[0]  = CanReadReg(RX_BUF0);
	pdat[1]  = CanReadReg(RX_BUF1);
	pdat[2]  = CanReadReg(RX_BUF2);
	pdat[3]  = CanReadReg(RX_BUF3);

	pdat[4]  = CanReadReg(RX_BUF0);
	pdat[5]  = CanReadReg(RX_BUF1);
	pdat[6]  = CanReadReg(RX_BUF2);
	pdat[7]  = CanReadReg(RX_BUF3);

	pdat[8]  = CanReadReg(RX_BUF0);
	pdat[9]  = CanReadReg(RX_BUF1);
	pdat[10] = CanReadReg(RX_BUF2);
	pdat[11] = CanReadReg(RX_BUF3);

	pdat[12]  = CanReadReg(RX_BUF0);
	pdat[13]  = CanReadReg(RX_BUF1);
	pdat[14]  = CanReadReg(RX_BUF2);
	pdat[15]  = CanReadReg(RX_BUF3);
}

//========================================================================
// 描述: CAN读取数据函数（标准帧格式11位）。
// 参数: *pdat: 接收数据缓冲区.
// 返回: CAN ID.
//========================================================================
uint16 CanReadMsg(uint8 *pdat)
{
	uint8 i,len;
	uint16 CanID;
	uint8 buffer[16];

	CanReadFifo(buffer);
	CanID = ((buffer[1] << 8) + buffer[2]) >> 5;
	len = buffer[0] & 0x0f;
	for(i=0;i<len;i++)
	{
		pdat[i] = buffer[i+3];
	}
	return CanID;
}

//========================================================================
// 描述: CAN读取数据函数（扩展帧格式28位）。
// 参数: *pdat: 接收数据缓冲区.
// 返回: CAN ID.
//========================================================================
uint32 CanReadMsg_EX(uint8 *pdat)
{
	uint8 i,len;
	uint32 CanID;
	uint8 buffer[16];

	CanReadFifo(buffer);
	CanID = (((uint32)buffer[1] << 24) + ((uint32)buffer[2] << 16) + ((uint32)buffer[3] << 8) + buffer[4]) >> 3;
	len = buffer[0] & 0x0f;
	for(i=0;i<len;i++)
	{
		pdat[i] = buffer[i+5];
	}
	return CanID;
}

//========================================================================
// 描述: CAN发送数据函数（标准帧格式11位）。
// 参数: canid: CAN ID; *pdat: 发送数据缓冲区; len:长度.
// 返回: none.
//========================================================================
void CanSendMsg(uint16 canid, uint8 *pdat, uint8 len)
{
	uint8 i,tx_buf;
	uint16 CanID;
	uint8 buffer[8];
	if(len > 8)len = 8;	//最长发送8字节数据

	CanID = canid << 5;
	for(i=0;i<8;i++)
	{
		if(i<len){
			buffer[i] = pdat[i];
		}else{
			buffer[i] = 0;
		}
	}
	CanWriteReg(TX_BUF0,len);//bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
	CanWriteReg(TX_BUF1,(uint8)(CanID>>8)); 
	CanWriteReg(TX_BUF2,(uint8)CanID);
	CanWriteReg(TX_BUF3,buffer[0]);

	CanWriteReg(TX_BUF0,buffer[1]);
	CanWriteReg(TX_BUF1,buffer[2]);
	CanWriteReg(TX_BUF2,buffer[3]);
	CanWriteReg(TX_BUF3,buffer[4]);

	CanWriteReg(TX_BUF0,buffer[5]);
	CanWriteReg(TX_BUF1,buffer[6]);
	CanWriteReg(TX_BUF2,buffer[7]);
	CanWriteReg(TX_BUF3,0);

	CanWriteReg(CMR ,0x04);		//发起一次帧传输
}

//========================================================================
// 描述: CAN发送数据函数（扩展帧格式28位）。
// 参数: canid: CAN ID; *pdat: 发送数据缓冲区.
// 返回: none.
//========================================================================
void CanSendMsg_EX(uint32 canid, uint8 *pdat, uint8 len)
{
	uint8 i;
	uint32 CanID;
	uint8 buffer[8];
	if(len > 8)len = 8;	//最长发送8字节数据

	CanID = canid << 3;
	for(i=0;i<8;i++)
	{
		if(i<len){
			buffer[i] = pdat[i];
		}else{
			buffer[i] = 0;
		}
	}

	CanWriteReg(TX_BUF0,0x80 | len);////bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
	CanWriteReg(TX_BUF1,(uint8)(CanID>>24)); 
	CanWriteReg(TX_BUF2,(uint8)(CanID>>16));
    CanWriteReg(TX_BUF3,(uint8)(CanID>>8)); 
    
	CanWriteReg(TX_BUF0,(uint8)CanID);
	CanWriteReg(TX_BUF1,buffer[0]);
	CanWriteReg(TX_BUF2,buffer[1]);
	CanWriteReg(TX_BUF3,buffer[2]);
    
	CanWriteReg(TX_BUF0,buffer[3]);
	CanWriteReg(TX_BUF1,buffer[4]);
	CanWriteReg(TX_BUF2,buffer[5]);
	CanWriteReg(TX_BUF3,buffer[6]);
    
	CanWriteReg(TX_BUF0,buffer[7]);
    CanWriteReg(TX_BUF1,0x00);//数据填充
    CanWriteReg(TX_BUF2,0x00);
	CanWriteReg(TX_BUF3,0x00);
    
	CanWriteReg(CMR ,0x04);		//发起一次帧传输
}

//========================================================================
// 描述: CAN总线波特率设置函数。
// 参数: none.
// 返回: none.
//========================================================================
//CAN总线波特率=Fclk/((1+(TSG1+1)+(TSG2+1))*(BRP+1)*2)

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     1		//0~63
//24000000/((1+3+2)*2*2)=1000KHz

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     3		//0~63
//24000000/((1+3+2)*4*2)=500KHz

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     7		//0~63
//24000000/((1+3+2)*8*2)=250KHz

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     15	//0~63
//24000000/((1+3+2)*16*2)=125KHz

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     19	//0~63
//24000000/((1+3+2)*20*2)=100KHz

//#define TSG1    2		//0~15
//#define TSG2    1		//0~7
//#define BRP     39	//0~63
//24000000/((1+3+2)*40*2)=50KHz

//#define TSG1    15	//0~15
//#define TSG2    2		//0~7
//#define BRP     29	//0~63
//24000000/((1+16+3)*30*2)=20KHz

//#define TSG1    15	//0~15
//#define TSG2    2		//0~7
//#define BRP     59	//0~63
//24000000/((1+16+3)*60*2)=10KHz

//波特率默认为10Khz
#ifndef TSG1
#define TSG1       	15
#endif
#ifndef TSG2
#define TSG2       	2
#endif
#ifndef BRP
#define BRP       	59
#endif

#define SJW     1		//重新同步跳跃宽度

void CANSetBaudrate()
{
	CanWriteReg(BTR0,(SJW << 6) + BRP);
	CanWriteReg(BTR1,(TSG2 << 4) + TSG1);
}

//========================================================================
// 描述: CAN初始化函数。
// 参数: none.
// 返回: none.
//========================================================================
void CANInit(CAN_PIN rx_pin, CAN_PIN tx_pin)
{
	CANSetBaudrate();	//设置波特率
	
	CanWriteReg(ACR0,0x00);		//总线验收代码寄存器
	CanWriteReg(ACR1,0x00);
	CanWriteReg(ACR2,0x00);
	CanWriteReg(ACR3,0x00);
	CanWriteReg(AMR0,0xFF);		//总线验收屏蔽寄存器
	CanWriteReg(AMR1,0xFF);
	CanWriteReg(AMR2,0xFF);
	CanWriteReg(AMR3,0xFF);
    
	CanWriteReg(MR  ,0x00);     //双滤波设置

    P_SW1 &= ~(0x03 << 4); //先清零
    
    if ((CAN_RX_P00 == rx_pin) && (CAN_TX_P01 == tx_pin))
    {
        P0M1&=~0x01;P0M0&=~0x01;//双向IO口
        P0M1&=~0x02;P0M0&=~0x02;//双向IO口
        P_SW1 |= 0x00; 
    }
    else if ((CAN_RX_P50 == rx_pin) && (CAN_TX_P51 == tx_pin))
    {
        P5M1&=~0x01;P5M0&=~0x01;//双向IO口
        P5M1&=~0x02;P5M0&=~0x02;//双向IO口
        P_SW1 |= 0x10; 
    }
    else if ((CAN_RX_P42 == rx_pin) && (CAN_TX_P45 == tx_pin))
    {
        P4M1&=~0x04;P4M0&=~0x04;//双向IO口
        P4M1&=~0x20;P4M0&=~0x20;//双向IO口
        P_SW1 |= 0x20; 
    }
    else if ((CAN_RX_P70 == rx_pin) && (CAN_TX_P71 == tx_pin))
    {
        P7M1&=~0x01;P7M0&=~0x01;//双向IO口
        P7M1&=~0x02;P7M0&=~0x02;//双向IO口
        P_SW1 |= 0x30; 
    }
	
	AUXR2 |= 0x02;		//CAN模块被使能
}

#endif